<template>
  <div class="container">
    <form-create
      v-bind="$attrs"
      ref="formRef"
      v-model="formModel"
      v-model:api="formApi"
      :option="options"
      :rule="rules"
    />
  </div>
</template>

<script setup lang="ts">
  import { Api, FormRule } from '@form-create/arco-design';
  import { merge, toLower } from 'lodash-es';

  import { useDictStore } from '@/store';

  const props = defineProps({
    options: {
      type: Object,
      default: () => {
        return {};
      },
    },
    schema: {
      type: Array,
      required: true,
    },
    rules: {
      type: Object,
      default: () => {
        return {};
      },
    },
    autoLabelWidth: {
      type: Boolean,
      default: true,
    },
  });

  const emit = defineEmits(['register']);
  const dictStore = useDictStore();
  const formRef = ref();
  const formModel = ref();
  const formApi = ref<Api>();

  onMounted(() => {
    emit('register', formRef.value.$parent, formRef.value);
  });

  const options = computed(() => {
    return {
      form: {
        labelAlign: 'right',
        autoLabelWidth: props.autoLabelWidth,
        labelColProps: { span: 5 },
        wrapperColProps: { span: 19 },
      },
      wrap: {
        rowProps: { gutter: 16 },
      },
      submitBtn: false,
      ...props.options,
    };
  });

  const rules = computed(() => {
    if (props.schema) {
      return props.schema?.map((item: any) => {
        if (props.rules && props.rules[item.field]) {
          item.validate = props.rules[item.field];
        }
        if (item.type === 'a-tree-select') {
          item.props = item.props || {};
          item.props.fieldNames = item.props?.fieldNames ?? {
            key: 'id',
            title: 'name',
          };
        }
        const old = rules.value?.find((ele) => ele.field === item.field);
        item = merge(old || {}, item);
        return {
          ...item,
          options:
            (item.enumName && toLower(item.type) === 'select') ||
            (item.enumName && toLower(item.type) === 'radio')
              ? dictStore.getItems(item.enumName)
              : item.options,
          title: item.label ?? item.title,
          props: {
            allowClear: true,
            placeholder:
              toLower(item.type).includes('input') ||
              toLower(item.type).includes('password') ||
              toLower(item.type).includes('textarea')
                ? '请输入' + item.label
                : '请选择' + item.label,
            ...item.componentProps,
            ...item.props,
          },
          effect: {
            fetch: item.optionApi
              ? {
                  action: async () => {
                    return await item.optionApi();
                  },
                  to: item.optionTo || 'options',
                }
              : item.fetch,
            ...item.effect,
          },
        };
      });
    }
    return [];
  });

  const reload = () => {
    formApi.value?.reload(rules.value as FormRule[]);
  };

  const submit = async () => {
    const res = await formApi.value?.validate().catch((err) => {
      console.log(err);
    });
    if (res) {
      return formApi.value?.formData();
    }
  };

  const getFormData = () => {
    return formApi.value?.formData();
  };

  const setValues = (data: Recordable) => {
    formModel.value = data;
    formApi.value?.setValue(data);
    formApi.value?.reload(rules.value as FormRule[]);
  };

  const getValue = (field: string) => {
    return formApi.value?.getValue(field);
  };

  const setSchema = (field: string, data: any) => {
    formApi.value?.mergeRule(field, data);
  };

  const addSchema = (data: Recordable, index: number) => {
    formApi.value?.addSchema(data, index);
  };

  const delSchema = (field: string) => {
    formApi.value?.delSchema(field);
  };

  const setOptions = (field: string, data: any) => {
    formApi.value?.mergeRules({ [field]: { options: data } });
    formApi.value?.reload(rules.value as FormRule[]);
  };

  const setProps = (field: string, props: any) => {
    formApi.value?.mergeRules({ [field]: { props: props } });
    formApi.value?.reload(rules.value as FormRule[]);
  };

  const setRule = (field: string, rule: any) => {
    formApi.value?.mergeRule(field, rule);
    formApi.value?.reload(rules.value as FormRule[]);
  };

  const changeRule = (field: string, rule: any) => {
    formApi.value?.updateRule(field, rule);
    formApi.value?.reload(rules.value as FormRule[]);
  };

  defineExpose({
    formModel,
    reload,
    submit,
    getFormData,
    setValues,
    getValue,
    setSchema,
    addSchema,
    delSchema,
    setOptions,
    setProps,
    setRule,
    changeRule,
  });
</script>

<style scoped lang="less"></style>
